package com.hxzy.struts.filter;

import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.spi.LoggerFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.hxzy.struts.action.Action;

/**
 * Servlet Filter implementation class ChapterEncodingFilter
 */
public class ChapterEncodingFilter implements Filter {
	private String mvcConfXml;
    private String encoding;
    private Map<String, Class<Action>> actionMapping;
	public void destroy() {
		// TODO Auto-generated method stub
	}

	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		req.setCharacterEncoding(encoding);
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		Action action = getAction(request);		
		if (action != null) {
				String result = action.execute(request, response);
				request.getRequestDispatcher(result).forward(req, res);
		}
		chain.doFilter(request, response);
	}
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
		this.encoding=fConfig.getInitParameter("Encoding");
		mvcConfXml = fConfig.getServletContext().getClassLoader().getResource("mvn.xml").getPath();
		SAXReader saxReader = new SAXReader();
			try {
				buildActionMapping(saxReader.read(new File(mvcConfXml)));
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (DocumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
	}
	
	private void buildActionMapping(Document document) throws ClassNotFoundException {
		actionMapping=new Hashtable<String,Class<Action>>();
		Element rootElement = document.getRootElement();
		for (Element e : (List<Element>) rootElement.elements()) {
			actionMapping.put(e.attribute("name").getValue(),(Class<Action>) loadClass(e.attribute("class").getValue()));
		}
			
	}
	public Action getAction(HttpServletRequest request) {
		// TODO Auto-generated method stub
		
		String uri = request.getRequestURI();
		String contextPath = request.getContextPath();
		String actionPath = uri.substring(contextPath.length());
			try {
				return findClass(actionPath).newInstance();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		throw new RuntimeException(String.format("class corresponding to the %s is not found", actionPath));
	}
	private Class<Action> findClass(final String actionPath) throws ClassNotFoundException {
		return actionMapping.get(actionPath);
		/*SAXReader saxReader = new SAXReader();
		try {
			Document document = saxReader.read(new File(mvcConfXml));
			Element rootElement = document.getRootElement();
			for (Element e : (List<Element>) rootElement.elements()) {
				if (actionPath.equals(e.attribute("name").getValue())) {
					return (Class<Action>) loadClass(e.attribute("class").getValue());
				}
			}
		} catch (DocumentException e) {
		}
		throw new ClassNotFoundException(String.format("沒有找到与  %s 匹配的类 ", actionPath));*/
	}
	
	

	private Class loadClass(String className) {
		Class clazz = null;
		try {
			clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		if (clazz == null) {
			try {
				clazz = Class.forName(className);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return clazz;
	}

	
	public static class ActionException extends Exception {
		private static final long serialVersionUID = 1L;
	}
}
